#include "synchronousav.h"
#include <libavinclude.h>
#include "audiotask.h"
#include "unistd.h"
#include <QDebug>
#define AV_SYNC_THRESHOLD   0.01
#define AV_NOSYNC_THRESHOLD 10.0
SynchronousAV::SynchronousAV(AudioTask *pAudioTask,Out_handler * pReceive_handler)
{
    m_pReceive_handler  = pReceive_handler;

    m_pAudioTask = pAudioTask;

    frame_last_delay = 40e-3;

    frame_last_pts = 0;

    frame_timer     = (double)av_gettime() / 1000000.0;

    setExit(false);
}

SynchronousAV::~SynchronousAV()
{
     setExit(true);
}

bool SynchronousAV::receive_handler(unsigned char *data, int size, double pts)//rgb 数据
{
    double actual_delay, delay, sync_threshold, ref_clock, diff;

    delay = pts - frame_last_pts;
    if (delay <= 0 || delay >= 1.0)  //
    {
        // if incorrect delay, use previous one
        delay =  frame_last_delay;  //如果延迟大于一秒 或小于0秒 就用上一帧的延迟（一般视频不能1s 一帧）
    }

    frame_last_delay = delay;	//保存这一次播放的延时

    frame_last_pts =  pts;      //保存这一次播放的视频时刻

    ref_clock = m_pAudioTask->get_audio_clock();

    diff = pts - ref_clock;			//算出这张图pts 与当前音频 的时刻配不配 差距过大 就丢弃

    sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD;//算出延迟

    if (fabs(diff) < AV_NOSYNC_THRESHOLD)	//差距小于10秒
    {
        if (diff <= -sync_threshold)// 如果  diff 小于0  说明  音频播放太快
        {
            delay = 0;
        }
        else if (diff >= sync_threshold)//说明  视频频播放太快
        {
            delay = 2 * delay;
        }
    }

    // delay 就是此时  此帧图片 应该播放时的真实延时
    frame_timer += delay;
    // computer the REAL delay
    actual_delay = frame_timer - (av_gettime() / 1000000.0);//
    if (actual_delay < 0.010)
    {
        // Really it should skip the picture instead
        actual_delay = 0.010;
    }

    //先播放 再暂停Sleep
    if( m_bExit == false )
    {
        m_pReceive_handler->receive_handler(data,size,pts);
        usleep((actual_delay * 1000 + 0.5)*1000);
    }else
    {
        m_bExit ++;
        qDebug(QString::number(m_bExit).toLocal8Bit().data());//" m_bExit == true")
    }

    return true;
}

void SynchronousAV::setExit(int bEixt)
{
    m_bExit = bEixt;
}

